"""
供应链数据分析系统主程序
整合数据生成、处理、分析和可视化功能
"""

import os
import argparse
import logging
from datetime import datetime
from typing import Dict, List, Optional

import pandas as pd
import numpy as np

from src.data.data_generator import SupplyChainDataGenerator
from src.data.make_dataset import DataLoader
from src.models.inventory_model import InventoryAnalyzer
from src.models.order_fulfillment import OrderFulfillmentAnalyzer
from src.models.cost_analyzer import CostAnalyzer
from src.models.demand_forecast_analyzer import DemandForecastAnalyzer
from src.visualization.visualization import SupplyChainVisualizer

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

class SupplyChainAnalysisSystem:
    """供应链数据分析系统类"""
    
    def __init__(self, data_dir: str = "data", output_dir: str = "reports"):
        """
        初始化供应链数据分析系统
        
        参数:
            data_dir: 数据目录
            output_dir: 输出目录
        """
        self.data_dir = data_dir
        self.raw_dir = os.path.join(data_dir, "raw")
        self.processed_dir = os.path.join(data_dir, "processed")
        self.output_dir = output_dir
        self.figures_dir = os.path.join(output_dir, "figures")
        
        # 确保目录存在
        for dir_path in [self.data_dir, self.raw_dir, self.processed_dir, self.output_dir, self.figures_dir]:
            if not os.path.exists(dir_path):
                os.makedirs(dir_path)
                logger.info(f"创建目录: {dir_path}")
        
        # 初始化组件
        self.data_loader = DataLoader(data_dir=data_dir)
        self.data_generator = SupplyChainDataGenerator()
        self.inventory_analyzer = InventoryAnalyzer()
        self.order_analyzer = OrderFulfillmentAnalyzer()
        self.cost_analyzer = CostAnalyzer()
        self.demand_analyzer = DemandForecastAnalyzer()
        self.visualizer = SupplyChainVisualizer(output_dir=self.figures_dir)
        
        # 数据字典
        self.data_dict = {}
        
        logger.info("供应链数据分析系统初始化完成")
    
    def generate_sample_data(self, order_count: int = 1000, seed: int = 42) -> Dict[str, pd.DataFrame]:
        """
        生成示例数据
        
        参数:
            order_count: 订单数量
            seed: 随机种子
            
        返回:
            生成的数据字典
        """
        logger.info(f"生成示例数据，订单数量: {order_count}")
        
        # 初始化数据生成器
        self.data_generator = SupplyChainDataGenerator(seed=seed)
        
        # 生成数据
        data_dict = self.data_generator.generate_all_data(order_count=order_count)
        
        # 保存数据
        self.data_generator.save_data(data_dict, output_dir=self.raw_dir)
        
        # 更新数据字典
        self.data_dict = data_dict
        
        logger.info("示例数据生成完成")
        return data_dict
    
    def load_data(self) -> Dict[str, pd.DataFrame]:
        """
        加载数据
        
        返回:
            加载的数据字典
        """
        logger.info("加载数据")
        
        data_dict = {}
        
        # 检查原始数据目录
        if os.path.exists(self.raw_dir):
            for file_name in os.listdir(self.raw_dir):
                if file_name.endswith('.csv'):
                    table_name = file_name.replace('.csv', '')
                    file_path = os.path.join(self.raw_dir, file_name)
                    try:
                        data_dict[table_name] = self.data_loader.load_csv(file_path)
                        logger.info(f"加载数据: {file_name}")
                    except Exception as e:
                        logger.error(f"加载数据失败: {file_name}, 错误: {e}")
        
        if not data_dict:
            logger.warning("未找到数据文件，请先生成数据")
        else:
            # 更新数据字典
            self.data_dict = data_dict
            logger.info(f"数据加载完成，共 {len(data_dict)} 个数据表")
        
        return data_dict
    
    def process_data(self) -> Dict[str, pd.DataFrame]:
        """
        处理数据
        
        返回:
            处理后的数据字典
        """
        logger.info("处理数据")
        
        if not self.data_dict:
            logger.warning("没有数据可处理，请先加载或生成数据")
            return {}
        
        processed_data = {}
        
        # 处理订单数据
        if 'orders' in self.data_dict:
            orders_df = self.data_dict['orders'].copy()
            
            # 确保日期列是日期时间类型
            date_columns = ['order_date', 'payment_date', 'processing_date', 'shipping_date', 'completion_date']
            for col in date_columns:
                if col in orders_df.columns:
                    orders_df[col] = pd.to_datetime(orders_df[col], errors='coerce')
            
            processed_data['orders'] = orders_df
            logger.info("处理订单数据完成")
        
        # 处理库存数据
        if 'inventory' in self.data_dict:
            inventory_df = self.data_dict['inventory'].copy()
            
            # 确保日期列是日期时间类型
            if 'expiry_date' in inventory_df.columns:
                inventory_df['expiry_date'] = pd.to_datetime(inventory_df['expiry_date'], errors='coerce')
            if 'last_updated' in inventory_df.columns:
                inventory_df['last_updated'] = pd.to_datetime(inventory_df['last_updated'], errors='coerce')
            
            processed_data['inventory'] = inventory_df
            logger.info("处理库存数据完成")
        
        # 处理库存移动数据
        if 'inventory_movements' in self.data_dict:
            movements_df = self.data_dict['inventory_movements'].copy()
            
            # 确保日期列是日期时间类型
            if 'movement_date' in movements_df.columns:
                movements_df['movement_date'] = pd.to_datetime(movements_df['movement_date'], errors='coerce')
            
            processed_data['inventory_movements'] = movements_df
            logger.info("处理库存移动数据完成")
        
        # 复制其他数据表
        for key, df in self.data_dict.items():
            if key not in processed_data:
                processed_data[key] = df.copy()
        
        # 保存处理后的数据
        for key, df in processed_data.items():
            output_path = os.path.join(self.processed_dir, f"{key}.csv")
            df.to_csv(output_path, index=False)
            logger.info(f"保存处理后的数据: {output_path}")
        
        # 更新数据字典
        self.data_dict = processed_data
        
        logger.info("数据处理完成")
        return processed_data
    
    def analyze_inventory(self) -> Dict:
        """
        分析库存
        
        返回:
            库存分析结果
        """
        logger.info("分析库存")
        
        if not self.data_dict:
            logger.warning("没有数据可分析，请先加载或生成数据")
            return {}
        
        # 设置分析器数据
        self.inventory_analyzer.set_data(
            inventory_df=self.data_dict.get('inventory'),
            movements_df=self.data_dict.get('inventory_movements'),
            products_df=self.data_dict.get('products'),
            orders_df=self.data_dict.get('orders'),
            order_items_df=self.data_dict.get('order_items')
        )
        
        # 执行分析
        inventory_metrics = self.inventory_analyzer.calculate_inventory_metrics()
        turnover_rate = self.inventory_analyzer.calculate_turnover_rate()
        expiry_risk = self.inventory_analyzer.analyze_expiry_risk()
        abc_classification = self.inventory_analyzer.analyze_abc_classification()
        stock_status = self.inventory_analyzer.analyze_stock_status()
        
        # 保存分析结果
        inventory_metrics.to_csv(os.path.join(self.output_dir, "inventory_metrics.csv"), index=False)
        turnover_rate.to_csv(os.path.join(self.output_dir, "turnover_rate.csv"), index=False)
        if not expiry_risk.empty:
            expiry_risk.to_csv(os.path.join(self.output_dir, "expiry_risk.csv"), index=False)
        abc_classification.to_csv(os.path.join(self.output_dir, "abc_classification.csv"), index=False)
        stock_status.to_csv(os.path.join(self.output_dir, "stock_status.csv"), index=False)
        
        # 生成可视化
        self.visualizer.plot_inventory_distribution(
            self.data_dict.get('inventory'),
            self.data_dict.get('products'),
            save_as="inventory_distribution.png"
        )
        self.visualizer.plot_expiry_risk(
            self.data_dict.get('inventory'),
            self.data_dict.get('products'),
            save_as="expiry_risk.png"
        )
        
        logger.info("库存分析完成")
        
        return {
            "inventory_metrics": inventory_metrics,
            "turnover_rate": turnover_rate,
            "expiry_risk": expiry_risk,
            "abc_classification": abc_classification,
            "stock_status": stock_status
        }
    
    def analyze_orders(self) -> Dict:
        """
        分析订单
        
        返回:
            订单分析结果
        """
        logger.info("分析订单")
        
        if not self.data_dict:
            logger.warning("没有数据可分析，请先加载或生成数据")
            return {}
        
        # 设置分析器数据
        self.order_analyzer.set_data(
            orders_df=self.data_dict.get('orders'),
            order_items_df=self.data_dict.get('order_items'),
            inventory_df=self.data_dict.get('inventory'),
            warehouses_df=self.data_dict.get('warehouses'),
            products_df=self.data_dict.get('products')
        )
        
        # 执行分析
        processing_times = self.order_analyzer.calculate_order_processing_times()
        efficiency_metrics = self.order_analyzer.analyze_fulfillment_efficiency()
        status_distribution = self.order_analyzer.analyze_order_status_distribution()
        
        # 保存分析结果
        processing_times.to_csv(os.path.join(self.output_dir, "order_processing_times.csv"), index=False)
        efficiency_metrics.to_csv(os.path.join(self.output_dir, "order_efficiency_metrics.csv"), index=False)
        status_distribution.to_csv(os.path.join(self.output_dir, "order_status_distribution.csv"), index=False)
        
        # 生成可视化
        self.visualizer.plot_order_fulfillment_time(
            self.data_dict.get('orders'),
            save_as="order_processing_times.png"
        )
        self.visualizer.plot_order_status_distribution(
            self.data_dict.get('orders'),
            save_as="order_status_distribution.png"
        )
        self.visualizer.plot_order_trend(
            self.data_dict.get('orders'),
            save_as="order_trend.png"
        )
        
        logger.info("订单分析完成")
        
        return {
            "processing_times": processing_times,
            "efficiency_metrics": efficiency_metrics,
            "status_distribution": status_distribution
        }
    
    def generate_dashboard(self) -> str:
        """
        生成综合数据看板
        
        返回:
            生成的HTML文件路径
        """
        logger.info("生成综合数据看板")
        
        if not self.data_dict:
            logger.warning("没有数据可视化，请先加载或生成数据")
            return ""
        
        # 生成看板
        dashboard_path = self.visualizer.generate_dashboard(
            self.data_dict,
            output_file="dashboard.html"
        )
        
        logger.info(f"综合数据看板已生成: {dashboard_path}")
        return dashboard_path
    
    def analyze_costs(self) -> Dict:
        """
        分析成本指标
        
        返回:
            成本分析结果
        """
        logger.info("分析成本指标")
        
        if not self.data_dict:
            logger.warning("没有数据可分析，请先加载或生成数据")
            return {}
        
        try:
            # 执行成本分析
            cost_analysis = self.cost_analyzer.generate_cost_analysis_report(
                inventory_df=self.data_dict.get('inventory', pd.DataFrame()),
                sales_df=self.data_dict.get('orders', pd.DataFrame()),
                purchases_df=self.data_dict.get('purchase_orders', pd.DataFrame()),
                transportation_df=self.data_dict.get('transportation', pd.DataFrame()),
                orders_df=self.data_dict.get('orders', pd.DataFrame()),
                deliveries_df=self.data_dict.get('deliveries', pd.DataFrame())
            )
            
            # 保存分析结果
            if 'error' not in cost_analysis:
                import json
                with open(os.path.join(self.output_dir, "cost_analysis.json"), 'w', encoding='utf-8') as f:
                    json.dump(cost_analysis, f, ensure_ascii=False, indent=2, default=str)
                
                logger.info("成本分析完成")
            else:
                logger.error(f"成本分析错误: {cost_analysis.get('error')}")
            
            return cost_analysis
            
        except Exception as e:
            logger.error(f"成本分析错误: {str(e)}")
            return {'error': str(e)}
    
    def analyze_demand_forecast(self) -> Dict:
        """
        分析需求预测准确性
        
        返回:
            需求预测分析结果
        """
        logger.info("分析需求预测准确性")
        
        if not self.data_dict:
            logger.warning("没有数据可分析，请先加载或生成数据")
            return {}
        
        try:
            # 准备需求预测数据
            if 'demand_forecasts' in self.data_dict and 'actual_demand' in self.data_dict:
                forecast_df = self.data_dict['demand_forecasts'].copy()
                actual_df = self.data_dict['actual_demand'].copy()
                
                # 合并实际值和预测值
                analysis_df = forecast_df.merge(
                    actual_df[['date', 'product_id', 'actual_demand']], 
                    on=['date', 'product_id'], 
                    how='inner'
                )
                
                if not analysis_df.empty:
                    # 执行需求预测分析
                    forecast_analysis = self.demand_analyzer.generate_forecast_analysis_report(analysis_df)
                    
                    # 保存分析结果
                    if 'error' not in forecast_analysis:
                        import json
                        with open(os.path.join(self.output_dir, "demand_forecast_analysis.json"), 'w', encoding='utf-8') as f:
                            json.dump(forecast_analysis, f, ensure_ascii=False, indent=2, default=str)
                        
                        logger.info("需求预测分析完成")
                    else:
                        logger.error(f"需求预测分析错误: {forecast_analysis.get('error')}")
                    
                    return forecast_analysis
                else:
                    logger.warning("无法合并需求预测和实际数据")
                    return {'error': '无法合并需求预测和实际数据'}
            else:
                logger.warning("缺少需求预测或实际需求数据")
                return {'error': '缺少需求预测或实际需求数据'}
                
        except Exception as e:
            logger.error(f"需求预测分析错误: {str(e)}")
            return {'error': str(e)}
    
    def run_full_analysis(self) -> Dict:
        """
        运行完整分析流程
        
        返回:
            分析结果
        """
        logger.info("运行完整分析流程")
        
        # 加载数据
        self.load_data()
        
        # 如果没有数据，生成示例数据
        if not self.data_dict:
            self.generate_sample_data()
        
        # 处理数据
        self.process_data()
        
        # 分析库存
        inventory_results = self.analyze_inventory()
        
        # 分析订单
        order_results = self.analyze_orders()
        
        # 分析成本
        cost_results = self.analyze_costs()
        
        # 分析需求预测
        forecast_results = self.analyze_demand_forecast()
        
        # 生成看板
        dashboard_path = self.generate_dashboard()
        
        logger.info("完整分析流程完成")
        
        return {
            "inventory_results": inventory_results,
            "order_results": order_results,
            "cost_results": cost_results,
            "forecast_results": forecast_results,
            "dashboard_path": dashboard_path
        }


def main():
    """主函数，处理命令行参数并执行相应操作"""
    parser = argparse.ArgumentParser(description='供应链数据分析系统')
    
    # 添加子命令
    subparsers = parser.add_subparsers(dest='command', help='子命令')
    
    # 生成数据命令
    generate_parser = subparsers.add_parser('generate', help='生成示例数据')
    generate_parser.add_argument('--orders', type=int, default=1000, help='生成的订单数量')
    generate_parser.add_argument('--seed', type=int, default=42, help='随机种子')
    
    # 加载数据命令
    load_parser = subparsers.add_parser('load', help='加载数据')
    
    # 分析库存命令
    inventory_parser = subparsers.add_parser('inventory', help='分析库存')
    
    # 分析订单命令
    order_parser = subparsers.add_parser('orders', help='分析订单')
    
    # 生成看板命令
    dashboard_parser = subparsers.add_parser('dashboard', help='生成数据看板')
    
    # 运行完整分析流程命令
    full_parser = subparsers.add_parser('full', help='运行完整分析流程')
    
    # 解析命令行参数
    args = parser.parse_args()
    
    # 初始化系统
    system = SupplyChainAnalysisSystem()
    
    # 执行相应命令
    if args.command == 'generate':
        system.generate_sample_data(order_count=args.orders, seed=args.seed)
    elif args.command == 'load':
        system.load_data()
    elif args.command == 'inventory':
        system.load_data()
        system.analyze_inventory()
    elif args.command == 'orders':
        system.load_data()
        system.analyze_orders()
    elif args.command == 'dashboard':
        system.load_data()
        system.generate_dashboard()
    elif args.command == 'full':
        system.run_full_analysis()
    else:
        # 默认运行完整分析流程
        system.run_full_analysis()


if __name__ == "__main__":
    main()